home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Atari Mega Archive 1
/
Atari Mega Archive - Volume 1.iso
/
program
/
spin3d.lzh
/
SPIN4.C
< prev
next >
Wrap
C/C++ Source or Header
|
1994-03-29
|
8KB
|
266 lines
/* *** SPIN4.C ***
***************
Will spin ==========> A triangle in 3 space <===============
!!! New things:
1) uses inline assembly routines to multiply
numbers...a little faster than previous versions
2) modifies #1 and makes 2 assembly multiplication routines,
one for COSINE multiplication and one for SINE mult.
(This GREATLY speeds up multiplication, see benchmrk.txt
for more details)
*** uses INTEGER ARITHMETIC for faster speed ***
** You can set up 3 diff projections
project : xy, xz, or yz
just my slight modification of draw3dline()
for xz projection do
x1 = p1.x y1 = p1.z
x2 = p2.x y2 = p2.z just DROP the y coord to project
onto the XZ plane!
March 28 ,1994 jeff bilger
jbilger@cs.tamu.edu
*/
#include <math.h>
#include <linea.h>
#include <osbind.h>
int pts[4][2] = {
320, 050,
120, 150,
520, 150,
320, 050
};
lineaport *theport;
long mu_global_s(); /* prototype, tells our
Assembly language function
to return a long int */
long mu_global_c(); /* multiply 32 bit global w/ a precomputed sin or cos value */
#define SCALE 2048L /* so far 2048 is the upper bounds scale
i can get W/O overflow */
#define BITSH 11 /* what to shift (ie DIVIDE) by. this number
2^11 = 2048 */
typedef struct {long x,y,z;} point3d; /* our faithful structure that defines a point in 3 space*/
/* these are used to allocate size of arrays */
#define NPTS 25 /* max allowable points */
#define NLINES 50
#define NFACES 50
#define I ( SCALE ) /* set up a SCALE factor */
point3d point_[NPTS] = /* define our triangle in 3d */
{
I,I,I, 3*I,I,I, 2*I,I,-I, 2*I,-I,I/2,
},
drawpt1[NPTS],drawpt2[NPTS]; /* for fast draw/erasing look up */
int
npts = 4, /* linefrom, lineto for drawing lines */
linefrom[NLINES] = {0,1,2,0,1,2}, /* set up lines to draw */
lineto[NLINES] = {1,2,0,3,3,3},
nlines = 6, /* number of lines */
x_offset=320, /* for viewport mapping */
y_offset=100,
z_offset=1;
long cos_2=2048; /* cos of 3 degrees * scale of 2048 */
long sin_2=107; /* sin of 3 degrees * scale of 2048 */
main()
{
register int i,j; /* use em for FOR loops */
point3d pointi; /* declare one instance of our point3d struct */
int color =1; /* color to draw triangle */
char com; /* for user input */
puts("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n");
puts("1-Spin Y 2-Spin X 3-Spin Z 9-Quit\n");
theport = a_init(); /* line a invokage */
theport -> plane0 = 1;
theport -> plane1 = 0;
theport -> plane2 = 0;
theport -> plane3 = 0;
for(i=0;i<nlines;i++) /* set up points-to-connect lookup table*/
{ drawpt1[i] = point_[linefrom[i]];
drawpt2[i] = point_[lineto[i]];
}
com = 0x32; /* set to spin about x */
while( com != 0x39)
{
if( Bconstat(2) ) /* if keypress */
com = Bconin(2); /* get input */
/* The main loop */
for(i=0;i<npts;i++)
{
pointi = point_[i]; /* get current point data. We do this for efficiency, since we will use this value many times within one loop
it's more efficient to compute it's value only once */
if(com == 0x31) { /* spin y */
point_[i].x =( mu_global_c(pointi.x) -
mu_global_s(pointi.z))>>BITSH; /* since our points are scaled AND or trig angles, sin&cos values are scaled we must divide by scale once here*/
point_[i].z =( mu_global_s(pointi.x) +
mu_global_c(pointi.z))>>BITSH;
}
if(com == 0x32) { /* spin x */
point_[i].y =( mu_global_c(pointi.y) +
mu_global_s(pointi.z))>>BITSH;
point_[i].z =( -(mu_global_s(pointi.y)) +
mu_global_c(pointi.z))>>BITSH;
}
if(com == 0x33) { /* spin z */
point_[i].x =( mu_global_c(pointi.x) +
mu_global_s(pointi.y))>>BITSH;
point_[i].y =( mu_global_c(pointi.y) -
mu_global_s(pointi.x))>>BITSH;
}
}
/* draw and erase triangle */
for(i=0;i<nlines;i++)
{ draw3dline(drawpt1[i],drawpt2[i],0); /*erase */
draw3dline(drawpt1[i]=point_[linefrom[i]],drawpt2[i]=point_[lineto[i]],color);
/* draw it */
}
}/* end of while */
} /* end of main */
/*******************************/
draw3dline(p1,p2,color)
point3d p1,p2;
int color;
{
int x1,y1,x2,y2;
/* project onto the xy plane */
x1 = (p1.x>>BITSH-5) + x_offset;
y1 = (p1.y>>BITSH-5) + y_offset;
x2 = (p2.x>>BITSH-5) + x_offset;
y2 = (p2.y>>BITSH-5) + y_offset;
theport -> plane0 = color;
a_line(x1,y1,x2,y2);
}
/***************************************************************/
/* We will now modify the assembly mult. routine to be as efficient
as possible. We will make 2 mult. routines, one to multiply
by a precomputed SINE value, and one to multiply by a precomputed
COSINE value
************************************************************/
/*******************************************************/
/* Multiply 1 16 bit(GLOBAL) SIGNED number b by a precomputed
SINE value of 3 degrees (then the sine value was * SCALE where
scale was 2048 )
and return the 32 bit result in D0
*** BIG NOTE:: b MUST be a GLOBAL var!!!!!!!!!!!!!!!!!
* WARNING * No test is made on the overflow bit (V) to see if
the result in c is indeed correct.
Send arguments to this prodecure by: c=multiply(b)
*/
long mu_global_s(b)
register long b; /* extern variables so b is placed in D7,*/
{
asm
{
muls #107,b /* generates muls #107,d7 */
move.l b,D0 /* generates move.l A7,(A5) */
/* Note: You MUST specify the size (.l) cause
if you just write 'move b,d0' Laser
C will assume move.w as the default */
}
}
/*************************************************
multiplies a number 'b' by a precomputed COSINE value
The Cos value is ===> cosine of 2 degrees * SCALE factor
where scale factor is defined. In our case the precomputed cos value
is 2045 */
long mu_global_c(b)
register long b; /* extern variable so b is placed in D7*/
{
asm
{
muls #2045,b /* generates muls #2045,d7 */
move.l b,D0 /* generates move.l A7,(A5) */
/* Note: You MUST specify the size (.l) cause
if you just write 'move b,d0' Laser
C will assume move.w as the default */
}
}
di(a,b)
register long int a,b;
{
asm
{
move.l a,D0
move.l b,D1
}
}